﻿using System;

namespace Riba.MVVMSL
{
	///<summary>
	///<para>You can use the Notifier's event to notify other ViewModels registering for it.</para>
	///<para>Through a commonly known Tag the notified ViewModel can check if the notification was meant for it.</para>
	///<see cref="Notifier"/>
	///</summary>
	///<remarks>
	///<para>There might be situations where while ViewModel A is executing an asynchronous operation, the NavigatorControl is requested to bring in front ViewModel B, but the instantiation of ViewModel B depends on the ExchangeData of ViewModel A.</para>
	///<para>In these case <see cref="ViewModelBase.IsDirty"/> can be used as pollable property to some extent but there might be situations where an event broadcast is more elegant.</para>
	///<para>The purpose of the <see cref="Notifier"/>-Property is to be able to synchronize asynchronous operations across several ViewModels.</para>
	///</remarks>
	public class Notifier
	{
		///<summary>
		///<para>Is raised to notify all interested derived ViewModel.</para>
		///</summary>
		public event EventHandler<NotificationEventArgs> Notify;

		///<summary>
		///<para>Raise this to notify all interested derived ViewModel.</para>
		///</summary>
		///<param name="e">See <see cref="NotificationEventArgs"/>.</param>
		public void RaiseNotify(NotificationEventArgs e)
		{
			if (Notify != null)
				Notify(this, e);
		}

		///<summary>
		///<para>Contains all informations that are needed during a Notify-event.</para>
		///</summary>
		public class NotificationEventArgs : EventArgs
		{
			///<summary>
			///<para>Defines a custom tag. ViewModels listening to the notify-event can sort out notifications with tags that don't interest them.</para>
			///</summary>
			///<value>string.Empty</value>
			public string Tag { get; private set; }
			
			///<summary>
			///<para>A data object to pass every kind of data.</para>
			///</summary>
			///<value>null</value>
			public object Data { get; private set; }

			///<summary>
			///<para>A callback to a method at the end of the notification.</para>
			///</summary>
			/// <value>null</value>
			public Action<object> Callback { get; private set; }

			///<summary>
			///<para>Initializes a new instance of the <see cref="NotificationEventArgs"/> class</para>
			///</summary>
			///<param name="tag">See <see cref="Tag"/>.</param>
			///<param name="data">See <see cref="Data"/>.</param>
			///<param name="callback">See <see cref="Callback"/>.</param>
			public NotificationEventArgs(string tag, object data, Action<object> callback = null)
			{
				Tag = tag;
				Data = data;
				Callback = callback;
			}
		}
	}
}